package com.itserver.controller.common;


import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.CircleCaptcha;
import com.itserver.ano.Log;
import com.itserver.ano.UpdateUser;
import com.itserver.pojo.LoginUser;
import com.itserver.pojo.PageResult;
import com.itserver.pojo.Result;
import com.itserver.pojo.sys.Menu;
import com.itserver.pojo.sys.User;
import com.itserver.service.sys.MenuService;
import com.itserver.service.sys.UserService;
import com.itserver.utils.Config;
import com.itserver.utils.JwtUtils;
import com.itserver.utils.RedisCache;
import com.itserver.utils.RequestHeader;
import jakarta.servlet.http.HttpSession;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;


import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Slf4j
@RestController
public class LoginController {

    @Autowired
    private UserService userService;
    @Autowired
    private MenuService menuService;
    @Autowired
    private RedisCache redisCache;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    @Autowired
    private Config config;

    public LoginController() {
        System.out.println("LoginController实例化");
    }

    /**
     * 验证码
     */
    @GetMapping("/captcha")
    public Result captcha(HttpSession session) {
        // 验证码获取次数限制
        String SessionId = "SessionId:"+ session.getId();
        String cacheCode = redisTemplate.opsForValue().get(SessionId);
        if(cacheCode != null ){
            // 讲cacheCode 转为数字
            int num = Integer.parseInt(cacheCode);
            // 超过10次 封禁
            if(num >= 10 ){
                return Result.error("验证码获取太频繁,请60s之后再试");
            }else{
                String value = String.valueOf(num + 1);
                redisTemplate.opsForValue().set(SessionId, value, 60, TimeUnit.SECONDS);
            }
        }else{
            redisTemplate.opsForValue().set(SessionId, "1", 60, TimeUnit.SECONDS);
        }

        CircleCaptcha captcha = CaptchaUtil.createCircleCaptcha(150,50,4,4);
        String code = captcha.getCode().toUpperCase();
        // 用 sessionId 当 key，避免前端传 uuid
        String key = "captcha:" + session.getId();
        redisTemplate.opsForValue().set(key, code, 60, TimeUnit.SECONDS);
        Map<String, Object> result = new HashMap<>();
        result.put("img", captcha.getImageBase64Data());
        return Result.success(result);
    }

    /*
    * 登录
    * */
    @PostMapping("/login")
    public Result login(@RequestBody LoginController.LUser user,HttpSession session) {
//        String key = "captcha:" + user.getUuid();
        String key =  session.getId();
        String cacheCode =  redisTemplate.opsForValue().get("captcha:"+key);
        if (cacheCode == null || !cacheCode.equalsIgnoreCase(user.getCode())) {
            return Result.error("验证码错误");
        }
        redisTemplate.delete("SessionId:"+ key); // 一次性使用

        LoginUser loginUser = userService.login(user.getUsername(),user.getPassword());
        log.info("用户登录:{}",user.getUsername());
        Object token = loginUser.getToken();
        //如果不是演示模式 检查当前登录用户 是否已经登录 如果已经登录 把上次登录的信息加入黑名单中
        if (config.getMode() == null || !config.getMode().equals("demo")){
            String LocalToken = redisCache.getTokenByUsername(user.getUsername());
            if (LocalToken != null && !LocalToken.isEmpty()) {
                redisCache.addInvalidToken(LocalToken);
                redisCache.deleteLoginUserToken(LocalToken);
            }
        }

        // 更新当前登录用户 和 token信息
        redisCache.addLoginUser(token.toString(),user.getUsername());
        HashMap<String,Object> data = new HashMap<>();
        data.put("token",token);
        data.put("exp",config.getExpire());
        return Result.success(data);
    }
    /*
    * 刷新登录 获取新的token
    * */
    @GetMapping("/refreshToken")
    public Result refreshToken() {
//        String NewToken = userService.refreshToken();
        log.info("用户刷新token");
        String Authorization = RequestHeader.getRequestHeader(config.getAuthentication());
        if(Authorization == null|| Authorization.isEmpty()){
            return Result.error("用户未登录");
        }
        Map<String,Object> UserInfo = JwtUtils.parseJWT(Authorization);
        if(UserInfo == null){
            return Result.error("token验证失败，请重新登录",401);
        }
        Map<String,Object> claims = new HashMap<>();
        User user = userService.getById((Integer) UserInfo.get("id"));
        claims.put("id",user.getId());
        claims.put("username",user.getUsername());
        claims.put("nickname",user.getNickname());
        claims.put("roles",user.getRoles());

        String token = JwtUtils.generateJwt(claims);

        //如果不是演示模式 检查当前登录用户 是否已经登录 如果已经登录 把上次登录的信息加入黑名单中
        if (config.getMode() == null || !config.getMode().equals("demo")){
            // 删除失效token并同步加入黑名单
            redisCache.deleteLoginUserToken(Authorization);
        }
        // 更新当前登录用户 和 token信息
        redisCache.addLoginUser(token,user.getUsername());
        // 从登录集合中删除 失效token 并同步加入黑名单
        redisCache.deleteLoginUserToken(Authorization);

        HashMap<String,Object> data = new HashMap<>();
        data.put("token",token);
        data.put("exp",config.getExpire());
        return Result.success(data);
    }
    // 创建一个静态内部类，用作登录用户类
    @Data
    public static class LUser {
        private String username;
        private String password;
        private String code;
        private String uuid;
    }
    /*
    * 登出
    * */
    @PostMapping("/loginOut")
    public Result logout() {
        log.info("用户登出");
        String Authorization = RequestHeader.getRequestHeader("Authorization");
        redisCache.addInvalidToken(Authorization);
        String uuid = RequestHeader.getUserInfo().get("uuid").toString();
        redisCache.deleteLoginUser(uuid);
        return Result.success();
    }
    /*
    * 获取当前系统在线用户数量
    * */
    @GetMapping("/getOnlineUser")
    public Result getOnlineUser() {
        Map<String, String> onlineUser = redisCache.getLoginUsers();
//        List<Object> onlineUsers = onlineUser.keySet().stream().map(item->{ return  (Object)item;}).toList();
        PageResult<Object> pageResult = new PageResult<>((long)onlineUser.size(),new ArrayList<>());
        log.info("获取当前系统在线用户{}",onlineUser.size());
        return Result.success(pageResult);
    }

    /*
    * 注册
    **/
    @PostMapping("/register")
    public Result register(@RequestBody User user) {
        userService.register(user);
        return Result.success();
    }

    /*
    * 重置密码
    * */
    @Log
    @PostMapping("/resetpwd")
    public Result resetpwd(@RequestBody User user) {
        userService.resetpwd(user);
        return Result.success();
    }

    /*
    * 修改密码
    * */
    @PostMapping("/updatepwd")
    @UpdateUser
    public Result updatepwd(@RequestBody UpdatePwd body) {
        userService.updatepwd(body);
        return Result.success();
    }
    // 修改密码静态内部类定义
    @Data
    public static class UpdatePwd {
        private String oldPwd;
        private String newPwd;
    }

    /*
    * 获取当前用户菜单
    * */
    @GetMapping("/getUserMenus")
    public Result getUserMenus() {
        PageResult<Menu> menus = menuService.getUserMenus();
        return Result.success(menus);
    }
    /*
    * 获取当前用户信息
    * */
    @GetMapping("/userInfo")
    public Result getUserInfo() {
        log.info("获取当前用户信息");
        UserInfo userInfo = userService.getUserInfo();

        return Result.success(userInfo);
    }
    //用户信息pojo定义
    @Data
    public static class UserInfo {
        private List<Map<String,Object> > roles;
        private Map<String,Object> user;
    }
}


